package com.hexinfo.dmpro.component.comparison.entity;

import cn.hutool.core.util.StrUtil;
import com.hexinfo.dmpro.component.comparison.enums.TableContrastEnums;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.util.HashMap;

/**
 * @Package com.hexinfo.dmpro.component.comparison.entity
 * @ClassName TableContrastDataManagementEntity
 * @Description 比对数据存放的单例
 * @Author Huang Yanyihe
 * @Date 2023/9/10 21:31
 * @Version v1.0
 **/
@Data
@Slf4j
@Repository
public class TableContrastDataManagementEntity {


    //比对数据Map集合
    private HashMap<String, HashMap<Long, String>> contrastMap = new HashMap<>();

    //查询状态Map集合
    private HashMap<String, TableContrastResultEntity> statusMap = new HashMap<>();

    /**
     * @Method ContrastIsRunning
     * @Param tableFlag
     * @Return boolean
     * @Description 判断任务是否正在进行
     * @Author Huang Yanyihe
     * @Date 2023/9/11 18:57
     * @Version V1.0
     */
    public boolean contrastIsRunning(String tableFlag){
            return this.getStatusMap().containsKey(tableFlag) &&
                    this.getStatusMap().get(tableFlag).getStatus().equals(TableContrastEnums.RUNNING.getValue());
    }

    /**
     * @Method contrastIsFail
     * @Param tableFlag
     * @Return boolean
     * @Description 判断比对任务是否失败
     * @Author Huang Yanyihe
     * @Date 2023/9/18 17:24
     * @Version V1.0
     */
    public boolean contrastIsFail(String tableFlag){
        return this.getStatusMap().containsKey(tableFlag) &&
                this.getStatusMap().get(tableFlag).getStatus().equals(TableContrastEnums.FAIL.getValue());
    }

    /**
     * @Method setFailStatus
     * @Param tableFlag
     * @Return void
     * @Description 设置比对任务状态为失败
     * @Author Huang Yanyihe
     * @Date 2023/9/18 17:24
     * @Version V1.0
     */
    public void setFailStatus(String tableFlag){ statusMap.get(tableFlag).setFailStatus(); }

    /**
     * @Method setAchieveStatus
     * @Param tableFlag
     * @Return void
     * @Description 设置比对任务状态为成功
     * @Author Huang Yanyihe
     * @Date 2023/9/18 17:24
     * @Version V1.0
     */
    public void setAchieveStatus(String tableFlag){
        statusMap.get(tableFlag).setAchieveStatus();
    }

    /**
     * @Method setFalseMessage
     * @Param tableFlag
     * @Param message
     * @Return void
     * @Description 设置任务失败信息
     * @Author Huang Yanyihe
     * @Date 2023/9/18 17:24
     * @Version V1.0
     */
    public void setFalseMessage(String tableFlag,String message){
        statusMap.get(tableFlag).setFalseMessage(message);
    }

    /**
     * @Method setErrorMessage
     * @Param tableFlag
     * @Param index
     * @Param data
     * @Return void
     * @Description 加锁后,写入错误信息
     * @Author Huang Yanyihe
     * @Date 2023/9/10 21:47
     * @Version V1.0
     */
    public synchronized void dataContrastError(String tableFlag, Long index, String data){
        //拒绝第二次比对错误的信息进入方法
        if (statusMap.get(tableFlag).getStatus().equals(TableContrastEnums.FAIL.getValue()) ||
                statusMap.get(tableFlag).getStatus().equals(TableContrastEnums.ACHIEVE.getValue()))
            return;
        //写入状态
        setFailStatus(tableFlag);

        //手动结束表比对任务,用于结束超时任务
        if(index.longValue() == -1L) {
            String errorMessage = StrUtil.format("任务:{}--{}--已比对数目:{}"
                    , tableFlag,data,statusMap.get(tableFlag).getSourceContrastNum());
            statusMap.get(tableFlag).setFalseMessage(errorMessage);
            log.info(errorMessage);
            return;
        }

        //数据不一致结束任务
        //错误信息写入开始
        log.error("数据不一致!");

        //获取比对失败的比对行
        String contrastData = contrastMap.get(tableFlag).get(index);

        //拼接写入错误信息
        String errorMessage = StrUtil.format
                ("数据不一致!--Line:{},sourceData:{},targetData:{}", index,data,contrastData);
        statusMap.get(tableFlag).setFalseMessage(errorMessage);

        try {
            //等待正在比对的任务结束、等待正在读取比对表的任务结束
            Thread.sleep(5000);

            //清空比对表内的数据
            contrastMap.remove(tableFlag);

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Method incrSourceContrastNum
     * @Param tableFlag
     * @Return void
     * @Description 加锁后,更新比对成功数据量
     * @Author Huang Yanyihe
     * @Date 2023/9/10 21:49
     * @Version V1.0
     */
    public synchronized void incrSourceContrastNum(String tableFlag){
        //更改源数据比对成功数目
        Long sourceContrastNum = statusMap.get(tableFlag).getSourceContrastNum();
        statusMap.get(tableFlag).setSourceContrastNum(sourceContrastNum+1L);
    }

}
